/*
 * WorkspaceDER.cpp
 *
 *  Created on: 28/04/2013
 *      Author: juan
 */

#include "gui/SubWindow/WorkspaceDER.h"
#include "gui/VisualComponents/der/VisualComponentEntity.h"
#include "gui/VisualComponents/der/VisualComponentCompositeAttribute.h"
#include "gui/VisualComponents/der/VisualComponentRelation.h"
#include "gui/VisualComponents/der/VisualComponentAttribute.h"
#include "gui/VisualComponents/der/VisualComponentViaDER.h"
#include "gui/VisualComponents/der/VisualComponentForkVia.h"
#include "gui/Tabs.h"
#include "xml/XmlReader.h"
#include <iostream>
using namespace std;

WorkspaceDER::WorkspaceDER(Diagram* diagram, bool enableEvents):Workspace(diagram,enableEvents) {
}

WorkspaceDER::~WorkspaceDER() {
}


void WorkspaceDER::validateDiagram(std::string archivo){

      fstream filestr;
      filestr.open(archivo.c_str(), std::fstream::out);

        if (filestr.is_open())
            m_diagram->validateDiagram(filestr);
        filestr.close();

}

void WorkspaceDER::store(XmlWriter& writer_rep, XmlWriter& writer_comp){
    Utils utils;
    updateDiagramSize();
    writer_rep.addCurrentNodeProperty(TARGET_NAME, m_diagram->getName().c_str());
    writer_rep.addCurrentNodeProperty(TARGET_SIZE_X, utils.convertToString(m_diagram->getSizeX()).c_str());
    writer_rep.addCurrentNodeProperty(TARGET_SIZE_Y, utils.convertToString(m_diagram->getSizeY()).c_str());
    writer_rep.addCurrentNodeProperty(TARGET_TYPE, utils.convertToString(m_diagram->getType()).c_str());
    writer_comp.addCurrentNodeProperty(TARGET_NAME, m_diagram->getName().c_str());

    for (std::vector<VisualDiagramComponent*>::iterator it = m_visualComponentList.begin(); it != m_visualComponentList.end(); ++it) {
    	(*it)->store(writer_rep, writer_comp, m_diagram);
    }
}

void WorkspaceDER::store(XmlWriter& writer_rep, XmlWriter& writer_comp, std::string tabName){
    Utils utils;
    updateDiagramSize();
    writer_rep.addCurrentNodeProperty(TARGET_NAME, tabName.c_str());
    writer_rep.addCurrentNodeProperty(TARGET_SIZE_X, utils.convertToString(m_diagram->getSizeX()).c_str());
    writer_rep.addCurrentNodeProperty(TARGET_SIZE_Y, utils.convertToString(m_diagram->getSizeY()).c_str());
    writer_rep.addCurrentNodeProperty(TARGET_TYPE, utils.convertToString(m_diagram->getType()).c_str());
    writer_comp.addCurrentNodeProperty(TARGET_NAME, m_diagram->getName().c_str());

    for (std::vector<VisualDiagramComponent*>::iterator it = m_visualComponentList.begin(); it != m_visualComponentList.end(); ++it) {
    	(*it)->store(writer_rep, writer_comp, m_diagram);
    }
}

void WorkspaceDER::on_load(XmlReader& readerModel, XmlReader & reader, Tabs* tabs) {

    try{
        Utils utils;
        //setea atributos del diagram
        reader.setCurrentNode(reader.getRoot());
        m_diagram->setName(reader.getCurrentNodeProperty(TARGET_NAME));
        m_diagram->setSize(utils.convertToUnsigned(reader.getCurrentNodeProperty(TARGET_SIZE_X)),
                utils.convertToUnsigned(reader.getCurrentNodeProperty(TARGET_SIZE_Y)));

        std::map< unsigned, VisualDiagramComponent* > visualComponents;
        std::map< unsigned, std::vector<int> > idsComponentesEntradas;
        const char* nameComponente;
        xmlNode* nodoAnterior = reader.getCurrentNodeChild();
        reader.setCurrentNode(nodoAnterior);

        while(reader.getCurrentNode()){
            nameComponente = reader.getCurrentNodeName();

            VisualDERComponent* visualComponent = NULL;
            if(!strcmp(nameComponente, TARGET_ENTITY))
                visualComponent = new VisualComponentEntity( m_diagram);
            else if (!strcmp(nameComponente, TARGET_ATTRIBUTE))
                visualComponent = new VisualComponentAttribute( m_diagram);
            else if (!strcmp(nameComponente, TARGET_RELATION))
                visualComponent = new VisualComponentRelation( m_diagram);
            else if (!strcmp(nameComponente, TARGET_COMPOSITEATTRIBUTE))
                visualComponent = new VisualComponentCompositeAttribute( m_diagram);
            else if (!strcmp(nameComponente, TARGET_VIA))
                visualComponent = new VisualComponentViaDER( m_diagram);
            else if (!strcmp(nameComponente, TARGET_FORK))
                visualComponent = new VisualComponentForkVia( m_diagram);

            if(visualComponent){
                visualComponent->load(reader, readerModel, m_diagram);
                addVisualComponent(visualComponent);
                nodoAnterior = reader.getCurrentNode();
                int identificador = utils.convertToInt(reader.getCurrentNodeProperty(TARGET_ID));
                visualComponents[identificador] = visualComponent;

                std::vector<Views> views;
                std::vector<int> ids;
                xmlNode* nodoActual = reader.getCurrentNodeChild();
                while(nodoActual){
                    reader.setCurrentNode(nodoActual);
                    if(strcmp(reader.getCurrentNodeName(), TARGET_PUNTO) != 0 && strcmp(reader.getCurrentNodeName(), TARGET_OTHER_DIAGRAM) != 0)
                        ids.push_back(utils.convertToInt(reader.getCurrentNodeProperty(TARGET_ID)));
                    if(strcmp(reader.getCurrentNodeName(), TARGET_OTHER_DIAGRAM) == 0){
                        Views view;
                        view.name = reader.getCurrentNodeProperty(TARGET_NAME);
                        view.id = utils.convertToUnsigned(reader.getCurrentNodeProperty(TARGET_ID));
                        views.push_back(view);
                    }
                    nodoActual = reader.nextNode();
                }
                idsComponentesEntradas[identificador] =  ids;
                for(unsigned i = 0 ; i < views.size() ; i++) {
                    Workspace* workspace = tabs->getWorkspace(views[i].name);
                    visualComponent->addView(workspace->getVisualComponent(views[i].id));
                }
            }

            reader.setCurrentNode(nodoAnterior);
            nodoAnterior = reader.nextNode();
            reader.setCurrentNode(nodoAnterior);

        }
        //Conecta los componentes
        for(unsigned i = 0; i < idsComponentesEntradas.size(); i++){
            std::vector<int> ids = idsComponentesEntradas[i];
            VisualDiagramComponent* visualComponent = visualComponents[i];
            for (unsigned j = 0; j < ids.size(); j++) {
                if ( ids[j] == -1)
                    continue;
                VisualComponentViaDER* visualVia = dynamic_cast<VisualComponentViaDER*>(visualComponents[ids[j]]);
                VisualComponentConector* connector =(VisualComponentConector*) visualComponent->getChildren()[j];
                int x =(*(dynamic_cast<ViaDER*>(visualVia->getComponent()))->getPoints().begin())->getX();
                int y =(*(dynamic_cast<ViaDER*>(visualVia->getComponent()))->getPoints().begin())->getY();
                int delta = 10;
                if( connector->getX() - delta <= x && x <= connector->getX() + delta  &&
                        connector->getY() - delta <= y && y <= connector->getY() + delta)
                        visualVia->setStartConector(connector);
                else
                        visualVia->setEndConector(connector);
                connector->setVia(visualVia);
            }
        }
    } catch (std::exception e) {
        throw std::runtime_error("Formato invalido del archivo xml");
    }
}

void WorkspaceDER::on_load(XmlReader& reader, Tabs* tabs) {
	try{
        Utils utils;
        //setea atributos del diagram
        reader.setCurrentNode(reader.getRoot());
        m_diagram->setName(reader.getCurrentNodeProperty(TARGET_NAME));
        m_diagram->setSize(utils.convertToUnsigned(reader.getCurrentNodeProperty(TARGET_SIZE_X)),
                utils.convertToUnsigned(reader.getCurrentNodeProperty(TARGET_SIZE_Y)));

        std::map< unsigned, VisualDiagramComponent* > visualComponents;
        std::map< unsigned, std::vector<int> > idsComponentesEntradas;
        const char* nameComponente;
        xmlNode* nodoAnterior = reader.getCurrentNodeChild();
        reader.setCurrentNode(nodoAnterior);

        while(reader.getCurrentNode()){
            nameComponente = reader.getCurrentNodeName();

            VisualDERComponent* visualComponent = NULL;
            if(!strcmp(nameComponente, TARGET_ENTITY))
                visualComponent = new VisualComponentEntity( m_diagram);
            else if (!strcmp(nameComponente, TARGET_ATTRIBUTE))
                visualComponent = new VisualComponentAttribute( m_diagram);
            else if (!strcmp(nameComponente, TARGET_RELATION))
                visualComponent = new VisualComponentRelation( m_diagram);
            else if (!strcmp(nameComponente, TARGET_COMPOSITEATTRIBUTE))
                visualComponent = new VisualComponentCompositeAttribute( m_diagram);
            else if (!strcmp(nameComponente, TARGET_VIA))
                visualComponent = new VisualComponentViaDER( m_diagram);
            else if (!strcmp(nameComponente, TARGET_FORK))
                visualComponent = new VisualComponentForkVia( m_diagram);

            if(visualComponent){
                visualComponent->load(reader, reader, m_diagram);
                addVisualComponent(visualComponent);
                nodoAnterior = reader.getCurrentNode();
                int identificador = utils.convertToInt(reader.getCurrentNodeProperty(TARGET_ID));
                visualComponents[identificador] = visualComponent;

                std::vector<Views> views;
                std::vector<int> ids;
                xmlNode* nodoActual = reader.getCurrentNodeChild();
                while(nodoActual){
                    reader.setCurrentNode(nodoActual);
                    if(strcmp(reader.getCurrentNodeName(), TARGET_PUNTO) != 0 && strcmp(reader.getCurrentNodeName(), TARGET_OTHER_DIAGRAM) != 0)
                        ids.push_back(utils.convertToInt(reader.getCurrentNodeProperty(TARGET_ID)));
                    if(strcmp(reader.getCurrentNodeName(), TARGET_OTHER_DIAGRAM) == 0){
                        Views view;
                        view.name = reader.getCurrentNodeProperty(TARGET_NAME);
                        view.id = utils.convertToUnsigned(reader.getCurrentNodeProperty(TARGET_ID));
                        views.push_back(view);
                    }
                    nodoActual = reader.nextNode();
                }
                idsComponentesEntradas[identificador] =  ids;
                for(unsigned i = 0 ; i < views.size() ; i++) {
                    Workspace* workspace = tabs->getWorkspace(views[i].name);
                    visualComponent->addView(workspace->getVisualComponent(views[i].id));
                }
            }

            reader.setCurrentNode(nodoAnterior);
            nodoAnterior = reader.nextNode();
            reader.setCurrentNode(nodoAnterior);

        }
        //Conecta los componentes
        for(unsigned i = 0; i < idsComponentesEntradas.size(); i++){
            std::vector<int> ids = idsComponentesEntradas[i];
            VisualDiagramComponent* visualComponent = visualComponents[i];
            for (unsigned j = 0; j < ids.size(); j++) {
                if ( ids[j] == -1)
                    continue;
                VisualComponentViaDER* visualVia = dynamic_cast<VisualComponentViaDER*>(visualComponents[ids[j]]);
                VisualComponentConector* connector =(VisualComponentConector*) visualComponent->getChildren()[j];
                int x =(*(dynamic_cast<ViaDER*>(visualVia->getComponent()))->getPoints().begin())->getX();
                int y =(*(dynamic_cast<ViaDER*>(visualVia->getComponent()))->getPoints().begin())->getY();
                int delta = 10;
                if( connector->getX() - delta <= x && x <= connector->getX() + delta  &&
                        connector->getY() - delta <= y && y <= connector->getY() + delta)
                        visualVia->setStartConector(connector);
                else
                        visualVia->setEndConector(connector);
                connector->setVia(visualVia);
            }
        }
    } catch (std::exception e) {
        throw std::runtime_error("Formato invalido del archivo xml");
    }
}
